package com.market.member.service.login;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.block.account.service.IMiniUserBaseInfoService;
import com.block.applet.service.AppletConfigInfoService;
import com.block.common.constant.AppRspCodeConstant;
import com.block.common.constant.RedisKeyConstant;
import com.block.common.model.dto.LoginReqDTO;
import com.block.common.model.dto.NewMemberDTO;
import com.block.common.service.IMemberCommonService;
import com.block.common.vo.ResponseVo;
import com.block.db.entity.AppletConfigInfo;
import com.block.db.entity.MemberBaseInfo;
import com.block.db.entity.MimiUserBaseInfo;
import com.block.db.mapper.MemberBaseInfoMapper;
import com.block.db.mapper.MiniUserBaseInfoMapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.market.member.enums.UserRegTypeEnum;
import com.market.member.enums.UserTypeEnum;
import com.market.member.model.dto.LoginResultDTO;
import com.market.member.service.ILoginTypeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;


/**
 * 微信登陆
 */
@Slf4j
@Service
public class WxLoginServiceImpl extends ILoginTypeService {

    @Resource
    MemberBaseInfoMapper memberBaseInfoMapper;

    @Resource
    MiniUserBaseInfoMapper miniUserBaseInfoMapper;

    @Autowired
    IMiniUserBaseInfoService miniUserBaseInfoService;


    @Autowired
    IMemberCommonService memberCommonService;

    @Autowired
    AppletConfigInfoService appletConfigInfoService;

    @Autowired
    StringRedisTemplate stringRedisTemplate;


    //private static String appId = "wx0b9a900434927c1d";
    //private static String secret = "b6d41160b41b68c0d1f51115e8f6b801";
    private static String getOpenIdUrl = "https://api.weixin.qq.com/sns/jscode2session";
    private static String getAccessToken = "https://api.weixin.qq.com/cgi-bin/token";
    private static String getPhoneNumber = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=";

    private final ObjectMapper objectMapper = new ObjectMapper();

    private static final long EXPIRE_TIME_DAYS = 7;

    @Override
    public ResponseVo toLogin(LoginReqDTO loginReqDTO) {

        String channelCode = loginReqDTO.getChannelCode();
        if (StringUtils.isEmpty(channelCode)) {
            return new ResponseVo(AppRspCodeConstant.PARAM_ERROR, "channelCode不能为空");
        }

        //String mobile = loginReqDTO.getMobile();

        AppletConfigInfo appletConfigInfo =getAppletConfigAppidAndSecret(loginReqDTO.getChannelCode());

        String loginCode = loginReqDTO.getLoginCode();
        if (StringUtils.isEmpty(loginCode)) {
            return new ResponseVo(AppRspCodeConstant.PARAM_ERROR, "loginCode不能为空");
        }

        //  获取 openId
        String openId = fetchOpenId(loginCode,appletConfigInfo);
        if (StringUtils.isEmpty(openId)) {
            return new ResponseVo(AppRspCodeConstant.SYS_EXCEPTION, "获取 openId 失败");
        }

        // 获取手机号
        String phoneNumber = fetchPhoneNumber(loginReqDTO.getMobile(),appletConfigInfo);
        if (StringUtils.isEmpty(openId)) {
            return new ResponseVo(AppRspCodeConstant.SYS_EXCEPTION, "获取手机号失败");
        }

        String mainlandMobile = validateAndExtractMainlandMobile(phoneNumber);
        if(mainlandMobile == null){
            return new ResponseVo(AppRspCodeConstant.SYS_EXCEPTION,"仅支持中国大陆手机号登录");
        }

        MimiUserBaseInfo existingUser = miniUserBaseInfoMapper.selectByOpenIdAndMobile(openId, phoneNumber);
        if (existingUser == null) {
            // 如果 existingUser 不存在，创建一个新的用户
            existingUser = new MimiUserBaseInfo();
            existingUser.setOpenId(openId);
            existingUser.setMobile(phoneNumber);
//            miniUserBaseInfoMapper.insert(existingUser);
            miniUserBaseInfoService.save(existingUser);
        }
        boolean isNewMember = false;
        MemberBaseInfo memberInfo = null;

        // 查询existingUser uid，直接查询对应的 memberInfo
        if (ObjectUtil.isEmpty(existingUser.getUid())) {
            // 根据手机号查询 memberInfo
            memberInfo = memberBaseInfoMapper.getBaseUserInfoByPhoneLock(existingUser.getMobile());
            if (ObjectUtil.isEmpty(memberInfo)) {
                // 如果 memberInfo 不存在，创建新的用户
                memberInfo = this.newMemberBaseInfo(existingUser.getMobile(), loginReqDTO);
                if (ObjectUtil.isEmpty(memberInfo)) {
                    log.error("【手机号直接登陆】创建用户失败");
                    return new ResponseVo(AppRspCodeConstant.SYS_EXCEPTION, "登录失败，请重试");
                }
                // 设置新成员标志
                isNewMember = true;
            }

            // 更新 existingUser 的 uid
            MimiUserBaseInfo updateEntity = new MimiUserBaseInfo();
            updateEntity.setId(existingUser.getId());
            updateEntity.setUid(memberInfo.getUid());
            int updateResult = miniUserBaseInfoMapper.updateById(updateEntity);
            if (updateResult > 0) {
                // 重新加载 existingUser 确保更新成功
                existingUser = miniUserBaseInfoMapper.selectById(existingUser.getId());
            }
        }

        if (ObjectUtil.isEmpty(memberInfo)){
            memberInfo = memberBaseInfoMapper.getMemberInfoByUidLock(existingUser.getUid());
        }

        LoginResultDTO loginResultDTO = new LoginResultDTO();
        loginResultDTO.setUid(memberInfo.getUid());
        loginResultDTO.setNewMember(isNewMember);
        loginResultDTO.setMemberBaseInfo(memberInfo);

        return new ResponseVo(AppRspCodeConstant.SUCCESS, loginResultDTO);
    }

    //  获取 openId
    private String fetchOpenId(String loginCode,AppletConfigInfo appletConfigInfo) {

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("appid", appletConfigInfo.getAppid());
        paramMap.put("secret", appletConfigInfo.getSecret());
        paramMap.put("js_code", loginCode);
        paramMap.put("grant_type", "authorization_code");

        try {
            String result = HttpUtil.createGet(getOpenIdUrl).form(paramMap).execute().body();
            JSONObject resultObject = JSON.parseObject(result);
            log.info("获取openId，返回结果"+result+"openid"+resultObject.getString("openid"));
            return resultObject.getString("openid");
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    // 获取手机号
    private String fetchPhoneNumber(String mobileCode,AppletConfigInfo appletConfigInfo) {
        String accessToken = fetchAccessToken(appletConfigInfo);
        if (StringUtils.isEmpty(accessToken)) {
            return null;
        }
        String url = getPhoneNumber + accessToken;

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("code", mobileCode);

        try {
            String result = HttpUtil.createPost(url).body(JSON.toJSONString(paramMap)).execute().body();
            JSONObject resultObject = JSON.parseObject(result);
            log.info("获取手机号，返回结果"+result+"---phoneNumber:"+resultObject.getJSONObject("phone_info").getString("phoneNumber"));
            if (resultObject.getInteger("errcode") == 0) {
                return resultObject.getJSONObject("phone_info").getString("phoneNumber");
            }
        } catch (Exception e) {
            return null;
        }
        return null;
    }

    // 获取 accessToken
    private String fetchAccessToken(AppletConfigInfo appletConfigInfo) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("appid", appletConfigInfo.getAppid());
        paramMap.put("secret", appletConfigInfo.getSecret());
        paramMap.put("grant_type", "client_credential");

        try {
            String result = HttpUtil.createGet(getAccessToken).form(paramMap).execute().body();
            JSONObject resultObject = JSON.parseObject(result);
            log.info("获取accessToken，返回结果"+result+"accessToken"+resultObject.getString("access_token"));
            return resultObject.getString("access_token");
        } catch (Exception e) {
            return null;
        }
    }

    public MemberBaseInfo newMemberBaseInfo(String mobile, LoginReqDTO loginReqDTO){
        NewMemberDTO newMemberDTO = new NewMemberDTO();
        newMemberDTO.setMobile(mobile);
        newMemberDTO.setChannelCode(loginReqDTO.getChannelCode());
        newMemberDTO.setChannelName(loginReqDTO.getChannelName());
        newMemberDTO.setRegAppCode(loginReqDTO.getAppCode());
        newMemberDTO.setRegReqIP(loginReqDTO.getReqIp());
        newMemberDTO.setType(UserTypeEnum.NORMAL.getValue());
        newMemberDTO.setRegType(UserRegTypeEnum.NORMAL.getValue());
        return  memberCommonService.saveNewMemberInfo(newMemberDTO);
    }

    /**
     * 从缓存或数据库中获取小程序配置信息。
     */
    private AppletConfigInfo getAppletConfigAppidAndSecret(String channelCode) {
        String redisKey = RedisKeyConstant.APPLET_CONFIG + channelCode;
        String appletConfigJson = stringRedisTemplate.opsForValue().get(redisKey);
        if (appletConfigJson == null) {
            // 直接从数据库获取配置信息
            AppletConfigInfo appletConfigInfo = appletConfigInfoService.selectAppletByChannelCode(channelCode);
            if (appletConfigInfo != null) {
                try {
                    // 将对象序列化为 JSON 字符串并存入 Redis
                    appletConfigJson = objectMapper.writeValueAsString(appletConfigInfo);
                    stringRedisTemplate.opsForValue().set(redisKey, appletConfigJson, EXPIRE_TIME_DAYS, TimeUnit.DAYS);
                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }
            }
        }
        try {
            // 反序列化 JSON 字符串为 AppletConfigInfo 对象
            return appletConfigJson != null ? objectMapper.readValue(appletConfigJson, AppletConfigInfo.class) : null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static String validateAndExtractMainlandMobile(String mobile) {
        String cleaned = mobile.replaceAll("[\\s\\-\\(\\)\\+/]+", "");
        if (cleaned.startsWith("+86")) {
            String pureMobile = cleaned.substring(3);
            return isValidMainlandMobile(pureMobile) ? pureMobile : null;
        }
        else if (cleaned.startsWith("86")) {
            String pureMobile = cleaned.substring(2);
            return isValidMainlandMobile(pureMobile) ? pureMobile : null;
        }
        else if (isValidMainlandMobile(cleaned)) {
            return cleaned;
        }
        else {
            return null;
        }
    }

    private static boolean isValidMainlandMobile(String mobile) {
        return mobile != null && mobile.matches("^1[3-9]\\d{9}$");
    }

}
